Using ADwin as a Multi-Channel Trigger Controller

by
Doug Rathburn
Keithley Instruments, Inc.



Introduction

Test system trigger controllers act as the central hub for sequencing test instruments. Using ADwin as the trigger controller allows the system to run much faster than implementing software triggers. The real-time nature of ADwin allows precise timing of triggers in and out of the test rack, which can open up new testing possibilities..

Building real-time control systems is difficult, if not impossible, with Microsoft® Windows® in the control loop. With the introduction of the ADwin system, high-speed, real-time data acquisition, process control, and analysis are now available in the Windows environment. The ADwin system provides assorted combinations of analog inputs and outputs as well as digital inputs and outputs. A dedicated microprocessor that can be programmed to perform most control applications is combined with the available I/O. Having a processor dedicated to controlling the I/O allows for reaction times down to 280ns.

As measurements and test data integrity become increasingly important, eliminating variability from the production process also increases in importance. Eliminating timing variability in the test system often requires precise trigger control. This note will show and explain the steps involved in building an example trigger controller with ADwin.


Test Description

For steady-state testing, the output of a source is set to a level and the device under test (DUT) is allowed to settle before the measurement is taken. This approach to testing is shown in Figure 1.

Figure 1. Effect of Measurement Timing Latencies on Steady-State Measurements

The ideal time to begin measuring the DUT output level is Td, which is just after it has settled. A measurement at this time will be accurate and can be taken with minimum delay. This is the ideal case, but in practice, there is usually some measurement latency, resulting in the measurement actually being taken between Td and Tm. Measurement latencies can occur from measurement processing time, program execution time, software interrupts, and instrument command processing time, which ultimately reduce throughput.

For devices with dynamic output signals, measurements are often taken at several points in time. Taking several measurements can be useful for time domain, rise time, or frequency analysis. Figure 2 shows the effects of timing issues when measuring dynamic outputs.

Figure 2. Effect of Trigger Timing Jitter and Latencies on Dynamic Signal Measurements

The times T1 through T6, shown in Figure 2, represent the desired measurement times needed to characterize the DUT. Looking at T1, the trigger timing uncertainty (jitter) means that the reading can actually occur at any time between T- and T+. The uncertainty can yield measured values between V- and V+, which implies that timing jitter or overall timebase accuracy are potential sources of error in the test system.


Test System Description

A typical test configuration consists of some kind of source to provide stimulus to the device under test (DUT) and a measurement device to measure the response of the DUT. The actions of the test system are usually controlled with a computer through the IEEE-488 interface. This typical system is shown in Figure 3.

Figure 3. Typical GPIB-Based Test System

The system shown in Figure 3 triggers the instruments with software. Triggering with software is common because of its flexibility and ease of implementation. Be aware, however, that software triggering lends itself to large amounts of jitter. Time variation between two subsequent events in Windows may vary by up to 50ms, even for compiled programs written in C++. For many applications, having up to 50ms of jitter in the timebase between measurements is unacceptable. Figure 4 shows a test system configuration using ADwin as an external trigger controller. In this system, ADwin monitors the output of the source and triggers the meter to begin measuring the DUT. The ADwin system can reduce trigger jitter by over 100 times in this configuration.

Figure 4. ADwin System Block Diagram

The ADwin system shown in Figure 4 monitors the source output with an analog input channel. When it sees a rising edge from the source, it delays for a programmable amount of time, then sends an output trigger to the instrument via a digital output line. Figure 5 illustrates an ADwin system controlling ten sets of instruments simultaneously.

Figure 5. ADwin Controlling a 10-Channel System


Methods and Techniques

Analog and Digital I/O
The ADwin hardware family separates the processor from the I/O. This separation allows for a wide range of flexibility regarding the type of signal conditioning and number of analog and digital I/O channels available. Therefore, it is possible to expand the capabilities and channel count of the event-driven data acquisition.

For a trigger control unit using the analog input to monitor each instrument, the number of inputs must equal the number of digital outputs used to send the trigger signal to each. The number of input/output pairs available for each of the ADwin products is summarized in Table 1.

Table 1. ADwin Family Analog Input Selection
System Possible Analog Input/Digital Output Pairs
ADwin-Light 6 (12 with ADwin-ADL)
ADwin-Gold 16
ADwin-Pro 160


Digital Triggering
Even though this note concentrates on an analog input signal for triggering ADwin does not rule out the possibility of using digital input triggers. Just as ADwin polls the analog input looking for a rising edge, ADwin is capable of polling the digital inputs as well. The section "Alternative Solutions" details the various input and output configurations possible with ADwin systems.

State Machine
With multiple input and output channels, keeping track of all the channels can be challenging. One method of controlling an ordered control process is to program a simple state machine into ADwin. The actions that occur within the controller occur in a pre-determined sequence based on the prior state of the process. The state of each channel is saved into an array and, to advance to another state, the necessary condition for that state must be met (as well as having reached the previous state). Figure 6 shows the four states associated with detecting and triggering off of a voltage pulse.

Figure 6. States of a Voltage Pulse for Trigger Controller Implementation

The first state of the state machine is detecting the rising edge of the voltage pulse with an analog input channel. The second state involves delaying a programmed amount of time (i.e., trigger delay). The third state represents actually sending the digital output trigger to the instrument to start the measurement. After the trigger, ADwin must wait and detect the falling edge of the pulse to see that the pulse has been completed. Once the falling edge has been detected and the fourth state has been reached, the state machine resets and the hardware monitors the analog input at the first state.


Basic Programming Guidelines

The following example program is used to implement the test system shown in Figure 5. The program was written in ADbasic and was compiled and run on the ADwin processor.


' Define User inputs to the ADwin configuration
#DEFINE CountsThresh    par_1           ' Voltage threshold for second test
#DEFINE Delay                   par_2           ' Delay before trigger for 1st test
#DEFINE Hysterisis              par_3           ' Limit effect of noise on threshold

' Define ADwin outputs to be read by the user program
#DEFINE ADChan1         par_5   ' AD counts from ADwin card
#DEFINE ADChan2         par_6   ' Each variable represents a meter
#DEFINE ADChan3         par_7
#DEFINE ADChan4         par_8
#DEFINE ADChan5         par_9
#DEFINE ADChan6         par_10
#DEFINE ADChan7         par_11
#DEFINE ADChan8         par_12
#DEFINE ADChan9         par_13
#DEFINE ADChan10        par_14

' Define User input floating point parameters
#DEFINE VoltThreshold   fpar_1          ' Voltage threshold for first test


' Define Program Flags with understandable names
#DEFINE Unipolar                1
#DEFINE Bipolar                 0
#DEFINE ON                              1
#DEFINE OFF                             0

' Define state machine variables
#DEFINE S0      0                       ' Wait for 20V
#DEFINE S1      1                       ' Delay before sending output trigger
#DEFINE S2      2                       ' Send output trigger
#DEFINE S3      3                       ' Wait for V-src off


DIM State[10] AS SHORT                  ' Array of states for each channel
DIM Reading[10] AS LONG                 ' Array for ADC counts
DIM Counter[10] AS INTEGER              ' Array of delays for each channel
DIM Vsrc[10] AS INTEGER                 ' Save state of each meter Volt Source
DIM LocStateOdd AS INTEGER              ' Place holder for state machine
DIM LocStateEven AS INTEGER             ' Place holder for state machine

DIM NumMeter AS INTEGER                 ' Define number of meters in use
DIM Polarity AS INTEGER                 ' Define polarity of voltage input
DIM DelayCounts AS LONG                 ' Clock cycles for 1st delay
DIM MaxVoltInput AS FLOAT               ' Maximum input setting for board
DIM FullRange AS FLOAT                  ' Define full range of input for board
DIM TempTime AS FLOAT                   ' Temporary variable for ADwin timer
DIM MuxNum AS INTEGER                   ' Define mux channel for ADCs
DIM InputCounts1 AS INTEGER             ' Hold counts from ADC1
DIM InputCounts2 AS INTEGER             ' Hold counts from ADC2
DIM DummyExp AS FLOAT                   ' Hold dummy value for exponent calc
DIM a,b,i,j,k AS INTEGER                ' Loop variables

SUB TakeRdgs(Mux)
        SET_MUX(45)                                     ' Set mux to Grounded channel
        SET_MUX(Mux)                            ' Set mux to desired channels
        DummyExp = 4^3                          ' Delay to let mux settle
        START_CONV(3)                           ' Start A/D conversion
        WAIT_EOC(3)                                     ' Wait until ADCs are done
        InputCounts1 = READADC(1)       ' Read ADC1 counts into variable
        InputCounts2 = READADC(2)       ' Read ADC2 counts into variable
ENDSUB

INIT:                                                   ' INIT section is run once at beginning

' Initialize various ADwin functions
CONF_DIO 15                                     ' Configure digital I/O
DIGOUT_WORD(2047)                       ' Set 16-bit digital output (normal HI)
GLOBALDELAY             =       2500    ' Loop EVENT every 1000 25ns intervals
SET_MUX(0)                                      ' Select channel 1 for both ADC

' Initialize Program Variables
NumMeter        =       10
VoltThreshold   =       0.3                     ' Set voltage threshold for 1st test
Delay           =       100                             ' Delay in ms for 1st test
InputCounts1    =       0                       ' Initialize variable
InputCounts2    =       0                       ' Initialize variable
Hysterisis      =       5                               ' Noise compensation

' Calculate number of 25ns counts to reach Delay value
DelayCounts     =       (Delay*0.001)/(25E-9)

Polarity        =       Unipolar
MaxVoltInput    =       10
LocStateOdd     =       S0
LocStateEven    =       S0

' Change voltage input from user into ADC counts
IF (Polarity = Bipolar) THEN
        FullRange = MaxVoltInput * 2
        CountsThresh = ((4096 / FullRange) * VoltThreshold) + 2048
ELSE
        FullRange = MaxVoltInput
        CountsThresh = (4096 / FullRange) * VoltThreshold
ENDIF

' Initialize the various Array Variables
j = 0
k = 1                                                   ' Initialize variable
FOR i = 1 to NumMeter
        State[i] = S0                           ' Initialize each to first state
        Counter[i] = 0                          ' Initialize each channel counter
        Reading[i] = 0                          ' Initialize A/D value array
        Vsrc[i] = OFF                           ' Initialize all sources as off
NEXT i


' MUX configuration for ADCs (10-bit) with gain=1 for both
' Binary                Decimal ADC1    ADC2 Channel
' 00 00 000 000 0               1       2
' 00 00 001 001 9               3       4
' 00 00 010 010 18              5       6
' 00 00 011 011 27              7       8
' 00 00 100 100 36              9       10
' 00 00 101 101 45              11      12
' 00 00 110 110 54              13      14
' 00 00 111 111 63              15      16


EVENT:                                  ' EVENT section represents main program loop

GLOBALDELAY = 2500                      ' Program Loop Execution

INC j                                           ' Increment counter

LocStateOdd = State[j]                  ' Local variable as channel state
LocStateEven = State[j+1]
DelayCounts             =       (Delay*0.001)/(25E-9)   ' Calculate Delay

' ************  ACQUIRE A/D READINGS  **********

IF (j = 1) THEN                                 ' Acquire first two ADC channels
        MuxNum = 0                                      ' Define ADC Channel number
        TakeRdgs(MuxNum)                        ' Call ADC subroutine
        a = 1                                           ' Distinguish between ADCs
        b = 2
        ADChan1 = InputCounts1          ' Output Counts to global parameters
        ADChan2 = InputCounts2
ENDIF                                                   ' This pattern followed for all channels

IF (j = 3) THEN
        MuxNum = 9
        TakeRdgs(MuxNum)
        a = 3
        b = 4
        ADChan3 = InputCounts1
        ADChan4 = InputCounts2
ENDIF

IF (j = 5) THEN
        MuxNum = 18
        TakeRdgs(MuxNum)
        a = 5
        b = 6
        ADChan5 = InputCounts1
        ADChan6 = InputCounts2
ENDIF

IF (j = 7) THEN
        MuxNum = 27
        TakeRdgs(MuxNum)
        a = 7
        b = 8
        ADChan7 = InputCounts1
        ADChan8 = InputCounts2
ENDIF

IF (j = 9)THEN
        MuxNum = 36
        TakeRdgs(MuxNum)
        a = 9
        b = 10
        ADChan9 = InputCounts1
        ADChan10 = InputCounts2
ENDIF


Reading[a] = InputCounts1                               ' Output Counts to local parameters
Reading[b] = InputCounts2

' **********  BEGINNING OF STATE MACHINE  ************

IF (LocStateOdd = S0) THEN                              ' Wait for 1st rising edge 
        IF (Reading[a] >= CountsThresh + Hysterisis) THEN 
                                                        ' Compare reading from ADC1
                Counter[a] = READ_TIMER()               ' Read timer to begin trig delay
                State[a] = S1                                   ' Increment state machine
        ENDIF
ENDIF

IF (LocStateEven = S0) THEN                     ' Wait for 1st rising edge
        IF (Reading[b] >= CountsThresh + Hysterisis) THEN
                                                                        ' Compare reading from ADC2
                Counter[b] = READ_TIMER()       ' Read timer to begin trig delay
                State[b] = S1                           ' Increment state machine
        ENDIF
ENDIF

IF (LocStateOdd = S1) THEN                              ' Delay before triggering meter
        TempTime = READ_TIMER()                         ' Store timer in temp variable
        IF ((TempTime - Counter[a]) > DelayCounts) THEN  ' Compare time to delay
                CLEAR_DIGOUT(a)                                 ' Output trigger pulse
                State[a] = S2                                   ' Increment state machine
        ENDIF
ENDIF

IF (LocStateEven = S1) THEN                             ' Delay before triggering meter
        TempTime = READ_TIMER()                         ' Store timer in temp variable
        IF ((TempTime - Counter[b]) > DelayCounts) THEN ' Compare time to delay
                CLEAR_DIGOUT(b)                                 ' Output trigger pulse
                State[b] = S2                                   ' Increment state machine
        ENDIF
ENDIF

IF (LocStateOdd = S2) THEN                              ' Reset trigger line
        SET_DIGOUT(a)                                           ' Bring line to Normal HI
        State[a] = S3                                           ' Increment state machine
ENDIF

IF (LocStateEven = S2) THEN                             ' Reset trigger line
        SET_DIGOUT(b)                                           ' Bring line to Normal HI
        State[b] = S3                                           ' Increment state machine
ENDIF

IF (LocStateOdd = S3) THEN                              ' Verify V-src is turned off
        IF (Reading[a] < CountsThresh - Hysterisis) THEN
                                                                                ' Compare ADC1 to "zero"
                State[a] = S0                                   ' Reset State Machine
        ENDIF
ENDIF

IF (LocStateEven = S3) THEN                             ' Verify V-src is turned off
        IF (Reading[b] < CountsThresh - Hysterisis) THEN
                                                                                ' Compare ADC2 to "zero"
                State[b] = S0                                   ' Reset State Machine
        ENDIF
ENDIF
        
INC j                                                                   ' Increment counter

' *********  END OF STATE MACHINE  *********

IF (j = NumMeter) THEN
        j = 0                                           ' Reset j if loop count equals # of meters
ENDIF

FINISH:                                                 ' FINISH section runs once at end of program

Example Program

Keithley developed a downloadable ADbasic example program TriggerController.bas to create the trigger controller in the test system shown in Figure 5.

NOTE: The test programs that are provided are intended to illustrate the concepts presented in this note. The programs may need to be altered in order to accommodate desired test parameters and timing.

Equipment List

  1. PC running Windows® 95, 98, NT4, or 2000
  2. ADwin-9 real-time control hardware
  3. ADbasic real-time development environment
  4. Custom wiring harness for connecting to test setup

Alternative Solutions

The ADwin product family offers many different form factors, processors, and I/O in which to create the PID controller. The ADwin family includes:

ADwin-Light   PC ISA bus plug-in boards
  • Analog inputs and outputs (one 12-bit A/D) - expandable
  • Digital I/O
  • Optional counters and quadrature encoder
  • ISA communication with the PC
ADwin-GOLD   Stand-alone, external system
  • 16 analog inputs (16-bit @ 10ms & 12-bit @ 0.8ms) - BNC connections
  • 2 analog outputs (16-bit) - expandable
  • 32 digital I/Os, in blocks of 8 as input or output
  • Optional counter (event counter, encoder interface, period cycle, PWM)
  • ISA or USB communication with the PC
ADwin-PRO   Industrial, modular 19-inch system
  • Up to 4 CPUs per system
  • Modular and expandable:
    • 480 analog inputs (multiplexed or parallel)
    • 120 analog outputs
    • 480 digital I/Os
    • Thermocouples, RTD, counter, filters, isolation, etc.
    • CAN-bus, Profibus, RS-232, RS-485, RS-422
  • ISA or USB for communication with the PC

All three product variations can support up to 32Mbytes of RAM per processor and optional bootloader. The bootloader stores an ADbasic process(es) and begins running the process upon power-up. Therefore, once the ADwin hardware is programmed, it can be used as a stand-alone and without a PC.

Keithley also offers a range of digital trigger controllers that are compatible with the instrument Trigger Link bus. The Models KPC-TM and 2361 offer additional system triggering alternatives.